home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-04-25 | 6.2 KB | 183 lines | [TEXT/CWIE] |
- //================================================================================
- // Greg Anderson
- // db+
- //
- // Group control object
- // 16 May 1994
- //================================================================================
- #pragma once
-
- #ifndef __GROUPCONTROLOBJECT__
- #define __GROUPCONTROLOBJECT__
-
- #include "Int64.h"
-
- //
- // For TConstDataReference
- //
- #include "AbstractData.h"
-
- //
- // For REQUIREVALIDPOINTER
- //
- #include "Debug.h"
-
- //
- // Still needed?
- //
- #include "Exceptions.h"
-
- //
- // 64 records per group * 32 bytes per record
- // produces groups that are 4K
- //
- enum
- {
- kLongWordsPerRecord = 8, // 8*4 == 32 bytes
- kSingleRecordSize = (kLongWordsPerRecord * sizeof(long)),
- kRecordsPerGroup = 64, // 32 * 64 == 4K
- kLongWordsPerRecordShift = 3 // For multiplying by kLongWordsPerRecord
- };
-
- //
- // The only thing that the group control object knows
- // about the contents of a record is how to make a free
- // list.
- //
- enum
- {
- kRecordIDFlagsWord = 0, // Flags stored in longword 0
- kFreeNodeIDByte = 0, // Free node id stored in flags longword
- kFreeNodeLinkByte = 1, // Free node link stored longword 1
- kPreviousFreeNodeLinkByte = 2, // Only free data records are doubly-linked
- kFreeRecordIDBits = 0x3F000000, // If all of these bits are set, record is free
- kFreeDBRecordID = 0xFF000000, // Initial value for a free DB Record
- kFreeDataRecordID = 0x3F000000, // Initial value for a free data record
- kDataRecordIndicatorBits = 0xC0000000, // If these bits are clear, record is a data record
- kDataRecordPhysicalSizeBits = 0x00FF0000, // Encoded size of a data record stored in these bits
- kDataRecordPhysicalSizeShift = 16,
- kPreviousRecordPhysicalSizeBits = 0x0000FF00, // Encoded size of the previous data record
- kPreviousRecordPhysicalSizeShift = 8,
- kFreeRecordNotLinkedToTree = -2
- };
-
- class TDatabaseDocument;
- class TAbstractRecord;
- class TAbstractBackingStore;
-
- //
- // We can identify the group type by
- // looking at the first longword in
- // the group data; this will be the
- // ID longword of the record or data block.
- //
- // The first two bits of this longword
- // will be zero for data blocks, and
- // nonzero for record blocks.
- //
- enum GroupType
- {
- kInvalidGroup,
- kRecordGroup,
- kDataBlockGroup
- };
-
- //================================================================================
- // Class TGroupControlObject
- //================================================================================
- class TGroupControlObject
- {
- //
- // ----- Fields --------------------------------------------------------------
- //
-
- private:
- long* fRecordData;
- TDatabaseDocument* fDocument;
- long fFirstRecord;
- Boolean fRecordGroupHasChanged;
- TAbstractRecord* fRecordCursors[kRecordsPerGroup];
-
- //
- // ----- Methods -------------------------------------------------------------
- //
-
- public:
- TGroupControlObject(TDatabaseDocument* doc, long firstRecord) :
- fRecordData(nil),
- fDocument(doc),
- fFirstRecord(firstRecord),
- fRecordGroupHasChanged(false) { REQUIREVALIDPOINTER(doc); this->InitializeRecordCursors(); };
- ~TGroupControlObject();
- void InitializeRecordCursors();
-
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
- // Public interface:
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-
- public:
- Int64 DocumentKeySpace();
-
- void CacheCreatedCursor(long recordIndex, TAbstractRecord* cursor);
- void NotifyCursorReleased(const TAbstractRecord* cursor);
-
- long LongwordsInRecord(long recordIndex) const;
- long BlockEncodedPhysicalSize(long recordIndex) const;
- void SetBlockEncodedPhysicalSize(long recordIndex, long newEncodedSize);
- long BlockPhysicalSize(long recordIndex) const { return this->LongwordsInRecord(recordIndex) * sizeof(long); }
-
- TAbstractRecord* GetRecord(long recordIndex);
-
- long GetRecordWord(long recordIndex, long longwordNumber) const;
- long* MakeRecordDataCopy(long recordIndex);
- void ChangeRecordData(long recordIndex, long* newData, Boolean inhibitCompare = false);
- const TConstDataReference RecordDataReference(long recordIndex, long dataType, long longwordNumber, long numberOfBytes) const;
-
- void RecordGroupHasChanged() { fRecordGroupHasChanged = true; }
- Boolean RecordGroupNeedsSave() const { return fRecordGroupHasChanged; }
-
- void PurgeIfUnreferenced();
- long InitializeNewGroup(long nextFreeNode, long& oneFreeIndex);
- long InitializeNewDataGroup(long desiredEncodedPhysicalSize, long& leftOverBlock);
- Boolean IndexIsFree(long recordIndex) const;
-
- long NextFreeIndex(long afterWhichIndex) const;
- long PreviousFreeIndex(long beforeWhichIndex) const;
- void RecordCursorStale(long recordToFree);
-
- long TrimBlock(long blockToSplit, long newEncodedPhysicalSize);
-
- //
- // Do debugging tests on the block links of an index
- //
- void Verify(long recordIndex, Boolean verifySubsequent = false);
-
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
- // Private methods:
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-
- protected:
- long CalculateRelativeIndex(long recordIndex) const;
- long NextRecordIndex(long recordIndex) const;
- long PreviousRecordIndex(long recordIndex) const;
- long FreeListToUse(long recordIndex) const { return this->BlockEncodedPhysicalSize(recordIndex); }
- Boolean IndexIsFreeAndOnFreeList(long recordIndex) const;
-
- void WriteRecordWord(long recordIndex, long longwordNumber, long theData);
- void WriteThroughToTransaction(long recordIndex, long longwordNumber, long theData, long theMask);
-
- void AllocateMemoryForRecordData();
- void ReadRecordGroupFromDisk(TAbstractBackingStore* backingStoreToUse = nil);
- void FlushChangesToDisk(TAbstractBackingStore* backingStoreToUse = nil);
- void PurgeRecordGroupFromMemory();
-
- TDatabaseDocument* DBDocument() const { return fDocument; };
- long* RecordData(long recordIndex) const;
- long FirstRecordIndex() const { return fFirstRecord; };
-
- long MergeFreeBlocks(long firstRecord, long recordToMerge);
-
- };
-
- #endif
-